#include <AVUITransform.h>
#include <AVUIMatrix.h>

namespace AVUI {

/// <summary>Creates an arbitrary affine matrix transformation that is used to manipulate objects or coordinate systems in a 2-D plane. </summary>
class MatrixTransform : public Transform
{
public:
    DECLARE_ELEMENT(MatrixTransform, Transform);

#pragma region Public Methods

    /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Media.MatrixTransform" /> class. </summary>
    MatrixTransform() { };

    /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Media.MatrixTransform" /> class with the specified transformation matrix. </summary>
    /// <param name="matrix">The transformation matrix of the new <see cref="T:System.Windows.Media.MatrixTransform" />.</param>
    MatrixTransform(const Matrix& matrix);

    /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Media.MatrixTransform" /> class with the specified transformation matrix values. </summary>
    /// <param name="m11">The value at position (1, 1) in the transformation matrix.</param>
    /// <param name="m12">The value at position (1, 2) in the transformation matrix.</param>
    /// <param name="m21">The value at position (2, 1) in the transformation matrix.</param>
    /// <param name="m22">The value at position (2, 2) in the transformation matrix.</param>
    /// <param name="offsetX">The X-axis translation factor, which is located at position (3,1) in the transformation matrix.</param>
    /// <param name="offsetY">The Y-axis translation factor, which is located at position (3,2) in the transformation matrix.</param>
    MatrixTransform(float m11, float m12, float m21, float m22, float offsetX, float offsetY);

    /// <summary>Creates a modifiable copy of this <see cref="T:System.Windows.Media.MatrixTransform" /> by making deep copies of its values. </summary>
    /// <returns>A modifiable deep copy of the current object. The <see cref="P:System.Windows.Freezable.IsFrozen" /> property of the cloned object returns false even if the <see cref="P:System.Windows.Freezable.IsFrozen" /> property of the source is true.</returns>
    TRefCountedPtr<MatrixTransform> Clone() { return (MatrixTransform*) Transform::Clone().get_Ptr(); }

    /// <summary>Creates a modifiable copy of this <see cref="T:System.Windows.Media.MatrixTransform" /> object by making deep copies of its values. This method does not copy resource references, data bindings, or animations, although it does copy their current values. </summary>
    /// <returns>A modifiable deep copy of the current object. The <see cref="P:System.Windows.Freezable.IsFrozen" /> property of the cloned object is false even if the <see cref="P:System.Windows.Freezable.IsFrozen" /> property of the source is true.</returns>
    TRefCountedPtr<MatrixTransform> CloneCurrentValue() { return (MatrixTransform*) Transform::CloneCurrentValue().get_Ptr(); };
 
#pragma endregion Public Methods

#pragma region Public Properties

    /// <summary>Gets or sets the <see cref="T:System.Windows.Media.Matrix" /> structure that defines this transformation. This is a dependency property. </summary>
    /// <returns>The <see cref="T:System.Windows.Media.Matrix" /> structure that defines this transformation. The default value is an identity <see cref="T:System.Windows.Media.Matrix" />. An identity matrix has a value of 1 in coefficients [1,1], [2,2], and [3,3]; and a value of 0 in the rest of the coefficients.</returns>
    Matrix get_Matrix() { return AVUI::UnboxValue<Matrix>(GetValue(get_MatrixProperty())); }
    void set_Matrix(const Matrix& value) { SetValue(get_MatrixProperty(), AVUI::BoxValue(value)); } 
    DECLARE_DEPENDENCY_PROPERTY(Matrix);

    /// <summary>Gets the <see cref="P:System.Windows.Media.MatrixTransform.Matrix" /> that represents this <see cref="T:System.Windows.Media.MatrixTransform" />.</summary>
    /// <returns>The matrix that represents this <see cref="T:System.Windows.Media.MatrixTransform" />.</returns>
    virtual Matrix get_Value() AVUI_OVERRIDE { ReadPreamble(); return get_Matrix(); }

#pragma endregion Public Properties

protected:

#pragma region Protected Methods

    virtual TRefCountedPtr<Freezable> CreateInstanceCore() AVUI_OVERRIDE { return object_allocate<MatrixTransform>().get_Ptr(); }

#pragma endregion Protected Methods

public:

#pragma region Internal Methods

    virtual void MultiplyValueByMatrix(Matrix* pResult, const Matrix& matrixToMultiplyBy) AVUI_OVERRIDE;
    virtual void TransformRect(Rect* pRect) AVUI_OVERRIDE;

#pragma endregion Internal Methods

#pragma region Internal Properties

    virtual bool get_IsIdentity() AVUI_OVERRIDE;

#pragma endregion Internal Properties

private:

#pragma region Private Methods

    static void StaticConstructor();

#pragma endregion Private Methods


};

}; // namespace AVUI
